using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ObjectPool : PoolBase<GameObject>
{
	//shared by all pools, used to record who create the GameObject for later destory
	public static Dictionary<GameObject,ObjectPool> Obj2PoolDic = new Dictionary<GameObject, ObjectPool>();
    public ObjectFactory factory;
    public string slug;
    public GameObject prefab;
    public Stack<GameObject> available;
    public List<GameObject> all;
    public int initCapacity;
    public delegate void InstantiatedCallBack(GameObject prefab, GameObject clonedObject);
    public InstantiatedCallBack instantiatedCallBack;
   
    public static ObjectPool Create(string slug,GameObject prefab, int initCapacity)
    {
        ObjectPool result = new ObjectPool();
		result.slug = slug;
        result.prefab = prefab;
        result.initCapacity = initCapacity;
        if (initCapacity > 0)
        {
            result.available = new Stack<GameObject>(initCapacity);
            result.all = new List<GameObject>(initCapacity);
        } 
        else
        {
            result.available = new Stack<GameObject>();
            result.all = new List<GameObject>();
        }        
        return result;
    }

    private GameObject CreateNewObject( ) {
        GameObject retObj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;

        all.Add(retObj);
        if (instantiatedCallBack != null) {
            instantiatedCallBack(prefab, retObj);
        }

        return retObj;
    }

    public override GameObject Spawn( ) 
    {
        GameObject result = null;
        if (available.Count == 0)
        {
            result = CreateNewObject( );
        }
        else 
        {
            do {
                result = available.Pop();
                if (result != null) 
                {
                    result.SetActive(true);
                }
            } while (result == null && available.Count > 0);
        }

        if (result == null) {
            result = CreateNewObject();
        }

        return result;
    }

    public override bool UnSpawn(GameObject obj) {
        if (obj == null) {
            return false;
        }
        if (!all.Contains(obj))
            return false;
        if (!available.Contains(obj)) {
            available.Push(obj);
            obj.SetActive(false);
            return true;
        }
        return false;
    }

    public void PrePopulate(int count) {
        for (int ii = 0; ii < count; ++ii) {
            GameObject obj = Spawn();
            UnSpawn(obj);
        }
    }

    public void UnSpawnAll() {
        for(int i=0;i<all.Count;i++)
        {
            if(all[i]!= null && all[i].active)
                UnSpawn(all[i]);
        }
    }

    public override void Clear()
    {
        all.Clear();
        available.Clear();
        UnSpawnAll();
        GameObject.Destroy(prefab);
    }
}
